package com.example.demo.utils.importUtils;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson2.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * 导入-监听器
 *
 * @author xiaobeibei@gogpay.cn
 * @date 2023-12-08 10:50
 */
public class ImportListener extends AnalysisEventListener<ImportDTO> {

    private static final Logger LOGGER = LoggerFactory.getLogger(ImportListener.class);

    /**
     * 每隔1000条存储数据库，然后清理list ，方便内存回收
     */
    private static final int BATCH_COUNT = 1000;

    /**
     * 缓存的数据，保存解析完成的数据
     */
    List<ImportDTO> list = new ArrayList<>();

    /**
     * 当前操作入参（若需要）
     */
    private final JSONObject form;

    /**
     * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
     *
     * @param client 移动端远程调用类
     * @param form   当前操作人入参
     */
    public ImportListener(JSONObject form) {
        this.form = form;
    }


    /**
     * 每一条数据解析都会来调用
     *
     * @param importDTO       读取的数据
     * @param analysisContext 解析上下文
     */
    @Override
    public void invoke(ImportDTO importDTO, AnalysisContext analysisContext) {
        // 获取当前行 可以用来按行读取以及其他校验操作
        Integer rowIndex = analysisContext.readRowHolder().getRowIndex();
        // 从数据行读取（文件有大标题，标题行）
        if (rowIndex >= 2) {
            list.add(importDTO);
            // 达到BATCH_COUNT了，需要先去存储一次数据库，防止数据几万条在内存，容易OOM
            if (list.size() >= BATCH_COUNT) {
                // 存储数据
                this.saveData();
                // 清理数据
                list.clear();
            }
        }
    }

    /**
     * 所有数据解析完成后调用
     *
     * @param analysisContext 解析上下文
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
       // 防止遗留数据，最后再存储一次
        if (list.size() > 0) {
            this.saveData();
            list.clear();
        }
        LOGGER.info("所有成绩数据解析完成！");
    }

    /**
     * 存储数据库
     */
    private void saveData() {
        LOGGER.info("{}条数据，开始存储数据库！", list.size());
        // form.put("list",list)
        // 根据业务逻辑处理缓存数据list
        LOGGER.info("存储数据库成功!");
    }
}
